package com.keqiang.chart.impl.axis.impl.pseudo3d.bar

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.text.Layout
import android.text.TextPaint
import androidx.annotation.ColorInt
import com.keqiang.chart.impl.axis.impl.bar.BarEntity
import com.keqiang.chart.utils.ObjectPool
import com.keqiang.chart.utils.draw3DRectangle
import com.keqiang.chart.utils.px
import com.keqiang.chart.utils.toRadian
import com.keqiang.utils.PaintUtils
import com.keqiang.utils.PaintUtils.getChartHeight
import kotlin.math.cos
import kotlin.math.sin

/**
 * 折线图默认点击高亮
 *
 * @author Created by wanggaowan on 2022/7/29 08:55
 */
open class BarChart3DHighLightRender @JvmOverloads constructor(
    chart: BarChart3D,
    /**
     * 覆盖在柱状图上遮罩的颜色
     */
    @ColorInt val maskColor: Int = 0x55000000) : HighLightRender(chart) {

    override fun onDraw(canvas: Canvas, start: Float, top: Float, end: Float, bottom: Float, data: List<BarEntity>) {
        val paint = ObjectPool.obtainPaint<Paint>()
        paint.style = Paint.Style.FILL

        val faceRadian = chart.faceDegrees.toRadian
        val faceCos = cos(faceRadian) * chart.xAxis.lineWidth
        val faceSin = sin(faceRadian) * chart.xAxis.lineWidth
        data.forEach {
            canvas.draw3DRectangle(paint, it.drawRectF.left, it.drawRectF.bottom, it.drawRectF.width() - faceCos,
                chart.xAxis.lineWidth, it.drawRectF.height() - faceSin, maskColor, chart.faceDegrees)
            getText(it)?.let { text ->
                drawValueText(canvas, it, start, end, top, text)
            }
        }

        ObjectPool.recyclePaint(paint)
    }

    /**
     * 绘制柱状图文本
     */
    protected open fun drawValueText(canvas: Canvas, data: BarEntity, start: Float, end: Float, top: Float, text: CharSequence) {
        val textPaint = ObjectPool.obtainPaint<TextPaint>(true)
        if (text.isNotEmpty()) {
            textPaint.color = getTextColor(data)
            textPaint.textSize = getTextSize(data)

            // 测量指定文本每行的最大宽度
            val split = text.split("\n")
            var maxOneLineWidth = 0f
            split.forEach { str ->
                maxOneLineWidth = textPaint.measureText(str).coerceAtLeast(maxOneLineWidth)
            }

            var maxWidth = (end - start).toInt()
            val textLine = PaintUtils.getTextLine(text, textPaint, maxWidth)
            val chartHeight = textPaint.getChartHeight()
            var align = Layout.Alignment.ALIGN_CENTER
            val drawX = if (maxOneLineWidth > maxWidth) {
                align = Layout.Alignment.ALIGN_NORMAL
                start
            } else {
                maxWidth = maxOneLineWidth.toInt()
                val cx = data.drawRectF.centerX()
                if (cx - start >= maxOneLineWidth / 2f) {
                    if (cx + maxOneLineWidth / 2f > end) {
                        align = Layout.Alignment.ALIGN_OPPOSITE
                        end - maxOneLineWidth
                    } else {
                        cx - maxOneLineWidth / 2f
                    }
                } else if (cx + maxOneLineWidth / 2f > end) {
                    align = Layout.Alignment.ALIGN_OPPOSITE
                    end - maxOneLineWidth
                } else {
                    align = Layout.Alignment.ALIGN_NORMAL
                    start
                }
            }

            val drawY = (data.drawRectF.top - chartHeight * textLine).coerceAtLeast(top)

            canvas.save()
            canvas.translate(drawX, drawY)
            PaintUtils.drawText(canvas, textPaint, text, maxWidth, Int.MAX_VALUE, align)
            canvas.restore()
        }

        ObjectPool.recyclePaint(textPaint)
    }

    /**
     * 获取需要绘制的文本
     */
    open fun getText(lineEntity: BarEntity): CharSequence? = null

    /**
     * 获取需要绘制的字体大小
     */
    open fun getTextSize(lineEntity: BarEntity): Float = 16f.px

    /**
     * 获取需要绘制的字体颜色
     */
    open fun getTextColor(lineEntity: BarEntity): Int = Color.BLACK
}